import java.util.ArrayList;

public class Terrain {
	
	// enums
    public static enum Wind { N, S, E, W, NE, NW, SE, SW };

    // constants
	private static final int lowSpread = 15;
    private static final int mediumSpread = 8;    
    private static final int highSpread = 4;    
    private static final int dieSpread = 100;
    private static final int jumpConst = 1000000;
    
    // variables
    private ArrayList<Cell> cells;
    private Wind wind;
    private int windSpeed;
    
    public Terrain(ArrayList<Cell> cells, Wind wind, int speed) {        
    	this.cells = cells;    	
    	this.wind = wind;                
        this.windSpeed = speed;
    }

    public Cell getCell(int x, int y) {
        for (Cell c : cells) {
            if (c.getX() == x && c.getY() == y) {
                return c;
            }
        }
        return null;
    }

    public ArrayList<Cell> getCells() {
		return cells;
	}
    
    public ArrayList<Cell> getNormalCells() {
        ArrayList<Cell> ret = new ArrayList<Cell>();
        for (Cell c : cells) {
            if (c.isNormal()) {
                ret.add(c);
            }
        }
        return ret;
    }

    public int getNumberOutCells() {
    	int ret = 0;
    	for (Cell c : cells)
    		if (c.isOut())
    			ret++;
    	return ret;
    }

    //function to spread a burning cell to its neighbors
    public void spread(Cell c) {
    	
        int xMove = 0;
        int yMove = 0;
        
        //arraylists to make random choice of xMove later
        ArrayList<Integer> xN = new ArrayList<Integer>();
        ArrayList<Integer> xNE = new ArrayList<Integer>();
        ArrayList<Integer> xE = new ArrayList<Integer>();
        ArrayList<Integer> xSE = new ArrayList<Integer>();
        ArrayList<Integer> xS = new ArrayList<Integer>();
        ArrayList<Integer> xSW = new ArrayList<Integer>();
        ArrayList<Integer> xW = new ArrayList<Integer>();
        ArrayList<Integer> xNW = new ArrayList<Integer>();
        
        //arraylists to make random choice of yMove later
        ArrayList<Integer> yN = new ArrayList<Integer>();
        ArrayList<Integer> yNE = new ArrayList<Integer>();
        ArrayList<Integer> yE = new ArrayList<Integer>();
        ArrayList<Integer> ySE = new ArrayList<Integer>();
        ArrayList<Integer> yS = new ArrayList<Integer>();
        ArrayList<Integer> ySW = new ArrayList<Integer>();
        ArrayList<Integer> yW = new ArrayList<Integer>();
        ArrayList<Integer> yNW = new ArrayList<Integer>();
        
        //North
        xN.add(0);
        xN.add(0);
        xN.add(-1);
        xN.add(1);
        yN.add(0);
        yN.add(-1);
        yN.add(-1);
        //end
        
        //Northeast
        xNE.add(1);
        xNE.add(0);
        yNE.add(0);
        yNE.add(-1);
        //end
        
        //East
        xE.add(1);
        xE.add(1);
        xE.add(0);
        yE.add(0);
        yE.add(0);
        yE.add(-1);
        yE.add(1);
        //end
        
        //Southeast
        xSE.add(1);
        xSE.add(0);
        ySE.add(0);
        ySE.add(1);
        //end
        
        //South
        xS.add(0);
        xS.add(0);
        xS.add(-1);
        xS.add(1);
        yS.add(0);
        yS.add(1);
        yS.add(1);
        //end
        
        //Southwest
        xSW.add(-1);
        xSW.add(0);
        ySW.add(0);
        ySW.add(1);
        //end
        
        //West
        xW.add(-1);
        xW.add(-1);
        xW.add(0);
        yW.add(0);
        yW.add(0);
        yW.add(-1);
        yW.add(1);
        //end
        
        //Northwest
        xNW.add(-1);
        xNW.add(0);
        yNW.add(0);
        yNW.add(-1);

        //end
        Cell toJump = c;

        if (wind == Wind.N) {          
            xMove = xN.get((int)(Math.random() * xN.size()));
            yMove = yN.get((int)(Math.random() * yN.size()));
            toJump = getCell((int)(Math.random() * 100),(int)(Math.random() * (c.getY()-15)));
        }
        
        else if (wind == Wind.NE) {
            xMove = xNE.get((int)(Math.random() * xNE.size()));
            yMove = yNE.get((int)(Math.random() * yNE.size()));
            toJump = getCell((c.getX()+15)+(int)(Math.random() * (99-(c.getX()+15))+1),(int)(Math.random() * c.getY()));
        }
        
        else if (wind == Wind.E) {
            xMove = xE.get((int)(Math.random() * xE.size()));
            yMove = yE.get((int)(Math.random() * yE.size()));
            toJump = getCell((c.getX()+15)+(int)(Math.random() * (99-(c.getX()+15))+1),(int)(Math.random() * 100));
        }    
        
        else if (wind == Wind.SE) {
	        xMove = xSE.get((int)(Math.random() * xSE.size()));
	        yMove = ySE.get((int)(Math.random() * ySE.size()));
	        toJump = getCell((c.getX()+15)+(int)(Math.random() * (99-(c.getX()+15))+1),(c.getY()+15)+(int)(Math.random() * (99-(c.getY()+15))+1));
        }
        
        else if (wind == Wind.S) {
            xMove = xS.get((int)(Math.random() * xS.size()));
            yMove = yS.get((int)(Math.random() * yS.size()));
            toJump = getCell((int)(Math.random() * 100),(c.getY()+15)+(int)(Math.random() * (99-(c.getY()+15))+1));
        }

        else if (wind == Wind.SW) {
            xMove = xSW.get((int)(Math.random() * xSW.size()));
            yMove = ySW.get((int)(Math.random() * ySW.size()));
            toJump = getCell((int)(Math.random() * c.getX()),(c.getY()+15)+(int)(Math.random() * (99-(c.getY()+15))+1));
        }
        
        else if (wind == Wind.W) {
            xMove = xW.get((int)(Math.random() * xW.size()));
            yMove = yW.get((int)(Math.random() * yW.size()));
            toJump = getCell((int)(Math.random() * (c.getX()-15)),(int)(Math.random() * 100));
        }

        else if (wind == Wind.NW) {
            xMove = xNW.get((int)(Math.random() * xNW.size()));
            yMove = yNW.get((int)(Math.random() * yNW.size()));
            toJump = getCell((int)(Math.random() * c.getX()-15),(int)(Math.random() * (c.getY()-15)));
        }
         
        // sem vento
        else { 
            xMove = -1 + (int)(Math.random() * ((2-(-1))));
            yMove = -1 + (int)(Math.random() * ((2-(-1))));
            toJump = getCell((int)(Math.random() * 100),(int)(Math.random() * 100));
        }

        c.increaseFireTicks();
        
        Cell neigh = getCell(c.getX() + xMove, c.getY() + yMove);
        
        // se a celula neighbour nao existe (esta nas bordas do mapa), entao retorna logo
        if (neigh == null)
        	return;
            
        // probabilidade de fazer jump é directamente proporcional à velocidade do vento
        int jump = (int)(Math.random() * (jumpConst/windSpeed) );        
        
        // so faz jump se numero random for 0
        if (jump == 0) 
            if (toJump != null && toJump.isNormal() && !toJump.isNone())
                toJump.setOnFire();
        
        if (neigh.isNormal()) {
        	
			if (neigh.getWaterTicks() == 0) {
	    	
		        if (neigh.isLow() && c.getFireTicks() % lowSpread == 0)
		    		neigh.setOnFire();
		
		        if (neigh.isMedium() && c.getFireTicks() % mediumSpread == 0)
		    		neigh.setOnFire();                    	
		
		        if (neigh.isHigh() && c.getFireTicks() % highSpread == 0)
					neigh.setOnFire();		        
			}
            
        }

        if (c.getFireTicks() < dieSpread) {
        	c.setColorBurning();
        }else
            c.setBurnt();
    }
        
    public static String getSWind(int iWind) {
    	if (iWind == 1) return "N";
    	else if (iWind == 2) return "NE";
    	else if (iWind == 3) return "E";
    	else if (iWind == 4) return "SE";
    	else if (iWind == 5) return "S";
    	else if (iWind == 6) return "SW";
    	else if (iWind == 7) return "W";
    	else return "NW";    	
    }
    
}
